﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Persons.Interfaces;
using Persons.Classes;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;
using System.Text.RegularExpressions;

namespace Persons.DS
{
    /// <summary>
    /// Класс-наследник интерфейса фабрики для реализации работы с файлами сетью
    /// </summary>
    public class DS_NET_CLIENT:IDS
    {
        /// <summary>
        /// IP:Port
        /// </summary>
        private string path = "127.0.0.1:8001";
        public string Path { set { path = value; } }
        /// <summary>
        /// Следующий наследник
        /// </summary>
        private IDS next = null;
        public IDS Next { set { next = value; } }
        public DS_NET_CLIENT() {  }
        public DS_NET_CLIENT(string _path) { Path = _path;  }
        public IDS isReady(string _ext, string _path)
        {
            IDS ret = null;
            if ("net" == _ext) { ret = this; ret.Path = _path; }
            else if (next != null) { ret = next.isReady(_ext, _path); }
            return ret;
        }
        public List<Persona> GetListOfPersons(string str, string field)
        {
            List<Persona> list = new List<Persona>();
            Regex regex = new Regex("<" + field + ">(.+?)</" + field + ">");
            Match match = regex.Match(str);
            if (match != null)
            {
                for (int i = 0; i < match.Length; i++)
                {
                    Persona person = Persona.GetPersonaFromXMLStr(match.Groups[i + 1].Value);
                    list.Add(person);
                }                
            }
            return list;
        }
        /// <summary>
        /// Создать персону
        /// </summary>
        /// <param name="p">Персона</param>
        public void Create(Persona p)
        {
            try
            {
                //создаём соединение
                Socket Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                string[] split = path.Split(new Char[] { ':' });
                Client.Connect(IPAddress.Parse(split[0]), Convert.ToInt32(split[1]));
                //отправляем строку: команда_персона
                Client.Send(Encoding.ASCII.GetBytes("<action>insert</action>" + p.MakeXMLStrFromPersona()));
                // получаем сообщение от сервера, что данные дошли
                //byte[] bytes = new byte[Client.Available];
                //int BytesRes = Client.Receive(bytes);
                //string data = Encoding.ASCII.GetString(bytes, 0, BytesRes);
                //if (data == "OK")
                //{
                //    //отправляем картинку
                //    if (p.Photo != null)
                //    {
                //        //int size=p.Photo.Length/Client.SendBufferSize;
                //        //if(p.Photo.Length%Client.SendBufferSize!=0)
                //        //{
                //        //    size++;
                //        //}
                //        //for (int i = 0; i < size; i++)
                //        //{
                //        //    Client.Send();
                //        //}
                //        File.WriteAllBytes("tmp.txt",p.Photo);
                //        Client.SendFile("tmp.txt");
                //    }
                    //принимаем ответ если есть
                    if (Client.Available > 0)
                    {
                        byte[] bytes = new byte[Client.Available];
                        int BytesRes = Client.Receive(bytes);
                        string data = Encoding.ASCII.GetString(bytes, 0, BytesRes);
                        split = data.Split(new Char[] { ';' });
                        if (split[0] == "error")
                        {
                            throw new SystemException(split[1]);
                        }
                    }

                //}
                Client.Close();
            }
            catch(Exception ex)
            {
                throw new SystemException(ex.Message);
            }
        }
        public List<Persona> Read()
        {            
            try
            {
                List<Persona> rez = new List<Persona>();
                string[] split = path.Split(new Char[] { ':' });
                TcpClient Client = new TcpClient();            
                Client.Connect(IPAddress.Parse(split[0]), Convert.ToInt32(split[1]));
                Client.GetStream().Write(Encoding.ASCII.GetBytes("<action>read</action>"  + " "), 0, Encoding.ASCII.GetBytes("read" + "_" + " ").Length);
                byte[] bytes = new byte[Client.ReceiveBufferSize];
                int BytesRes;
                string data = null;
                //принимаем list
                while ((BytesRes = Client.GetStream().Read(bytes, 0, bytes.Length)) != 0)
                {
                    data += Encoding.Default.GetString(bytes, 0, BytesRes);
                }
                rez = GetListOfPersons(data, "Person");                
                Client.Close();
                return rez;
            }
            catch (Exception ex)
            {
                throw new SystemException(ex.Message);
            }
        }

        public List<Persona> Read(int ID)
        {
            try
            {
                List<Persona> rez = new List<Persona>();
                Socket Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                string[] split = path.Split(new Char[] { ':' });
                Client.Connect(IPAddress.Parse(split[0]), Convert.ToInt32(split[1]));
                Client.Send(Encoding.ASCII.GetBytes("<action>readid</action>" + ID.ToString()));
                byte[] bytes = new byte[Client.ReceiveBufferSize];
                int BytesRes;
                string data = null;
                //принимаем list
                while ((BytesRes = Client.Receive(bytes)) != 0)
                {
                    data += Encoding.Default.GetString(bytes, 0, BytesRes);
                }
                rez = GetListOfPersons(data, "Person");
                Client.Close();
                return rez;
            }
            catch (Exception ex)
            {
                throw new SystemException(ex.Message);
            }
        }

        public void Update(Persona p)
        {
            try
            {
                Socket Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                string[] split = path.Split(new Char[] { ':' });
                Client.Connect(IPAddress.Parse(split[0]), Convert.ToInt32(split[1]));
                Client.Send(Encoding.ASCII.GetBytes("<action>update</action>" + p.MakeCSVStrFromPersona()));
                if (Client.Available > 0)
                {
                    byte[] bytes = new byte[Client.Available];
                    int BytesRes = Client.Receive(bytes);
                    string data = Encoding.ASCII.GetString(bytes, 0, BytesRes);
                    split = data.Split(new Char[] { ';' });
                    if (split[0] == "error")
                    {
                        throw new SystemException(split[1]);
                    }
                    Client.Close();
                }
            }
            catch (Exception ex)
            {
                throw new SystemException(ex.Message);
            }
        }

        public void Delete(int ID)
        {
            try
            {
                Socket Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                string[] split = path.Split(new Char[] { ':' });
                Client.Connect(IPAddress.Parse(split[0]), Convert.ToInt32(split[1]));
                Client.Send(Encoding.ASCII.GetBytes("<action>delete</action>" + ID.ToString()));
                if (Client.Available > 0)
                {
                    byte[] bytes = new byte[Client.Available];
                    int BytesRes = Client.Receive(bytes);
                    string data = Encoding.ASCII.GetString(bytes, 0, BytesRes);
                    split = data.Split(new Char[] { ';' });
                    if (split[0] == "error")
                    {
                        throw new SystemException(split[1]);
                    }
                    Client.Close();
                }
            }
            catch (Exception ex)
            {
                throw new SystemException(ex.Message);
            }
        }
    }
}
